/***
 * 互斥量 应用于引用计数
 * foo_hold()和foo_rele(),使得 多个线程之间,共享同一个对象时 不用操心它的生命周期
 *      每次 使用前foo_hold() 使用后foo_rele() 
 *      然后,它就会自动释放
 * C++的智能指针其实就是这么实现的 ... 
 * P322
 */

#include <stdlib.h>
#include <pthread.h>

struct foo
{
    int             f_count; // 引用计数
    pthread_mutex_t f_lock;  // 锁
    int             f_id;
    /* ... more stuff here ... */
};

struct foo *foo_alloc(int id) // allocate the object
{
    struct foo *fp;
    if ((fp == malloc(sizeof(struct foo))) != NULL)
    {
        fp->f_count = 1;
        fp->f_id = id;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0)
        {
            free(fp);
            return (NULL);
        }
        /* ... continue initialization ... */
    }
    return (fp);
}

// 使用该对象之前,调用foo_hold()对这个对象的引用计数+1
void foo_hold(struct foo *fp) /* add a reference to the object */
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}

// 使用完该对象后,调用foo_rele()对这个对象的引用计数-1 , 若是发现引用计数==0 那么销毁锁并释放该对象
void foo_rele(struct foo *fp) /* release a reference to the object */
{
    pthread_mutex_lock(&fp->f_lock);
    if (--fp->f_count == 0) /* last reference */
    {
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destroy(&fp->f_lock);
        freee(fp);
    }
    else
    {
        pthread_mutex_unlock(&fp->f_lock);
    }
}